﻿using System;
using System.Diagnostics.Contracts;
using OpenLS.Drawing;

namespace OpenLS.Spreadsheet.Formats.Biff.OfficeArt
{
    internal class OfficeArtFBSE : OfficeArtBStoreContainerFileBlock
    {
        private MSOBLIPTYPE __type;
        private MSOBLIPTYPE _btMacOs;
        private MSOBLIPTYPE _btWin32;
        private int _cRef;
        private OfficeArtBlip _embeddedBlip;
        private uint _foDelay;
        private byte[] _nameData;
        private MD4Digest _rgbUid;
        private uint _size;
        private ushort _tag;

        private byte _unused1;
        private byte _unused2;
        private byte _unused3;

        public OfficeArtFBSE(OfficeArtBlip embeddedBlip)
        {
            Contract.Ensures(_rgbUid != null);
            _embeddedBlip = embeddedBlip;
            _cRef = 1;
            _btWin32 = embeddedBlip.Type;
            _btMacOs = embeddedBlip.Type;
            this.type = embeddedBlip.Type;
            _size = (uint) embeddedBlip.FullByteLength;
            this._rgbUid = embeddedBlip.GetDigest();
        }

        public OfficeArtFBSE()
        {
        }

        private MSOBLIPTYPE type
        {
            get
            {
                return __type;
            }
            set
            {
                __type = value;
            }
        }


        public override RecType RecordType
        {
            get { return RecType.OfficeArtFBSE; }
        }

        protected override byte Version
        {
            get { return 0x02; }
        }

        protected override int ByteLength
        {
            get
            {
                int result = 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + (_nameData == null ? 0 : _nameData.Length);
                if (_embeddedBlip != null)
                       result += _embeddedBlip.FullByteLength;
                return result;
            }
        }

        protected override void ReadNoHeader(OfficeArtReadContext context)
        {
#if DEBUG
            long position = context.BaseStream.Position;
#endif
            Contract.Assert(rhrecVer == 0x02);
            type = (MSOBLIPTYPE) rhrecInstance;
            Contract.Assert(rhrecType == RecType.OfficeArtFBSE);
            Contract.Assert(rhrecType == (RecType) 0xF007);
            _btWin32 = (MSOBLIPTYPE) context.ReadByte();
            _btMacOs = (MSOBLIPTYPE) context.ReadByte();
            Contract.Assert(this.type == _btWin32 || type == _btMacOs);
            _rgbUid = new MD4Digest(context.Reader);
            _tag = context.ReadUInt16();
            _size = context.ReadUInt32();
            _cRef = context.ReadInt32();
            _foDelay = context.ReadUInt32();
            _unused1 = context.ReadByte();
            byte cbName = context.ReadByte();
            _unused2 = context.ReadByte();
            _unused3 = context.ReadByte();
            if (cbName > 0)
                _nameData = context.ReadBytes(cbName);
#if DEBUG
            Contract.Assert(context.BaseStream.Position - position ==
                            1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + (_nameData == null ? 0 : _nameData.Length));
#endif
            if (type != MSOBLIPTYPE.msoblipERROR)
            {
                _embeddedBlip = (OfficeArtBlip) ReadRecord(context);
                Contract.Assert(_embeddedBlip.FullByteLength == _size);
#if DEBUG
                Contract.Assert(context.BaseStream.Position - position ==
                                1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + (_nameData == null ? 0 : _nameData.Length) +
                                _embeddedBlip.FullByteLength);
                Contract.Assert(rhrecLen ==
                                1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + (_nameData == null ? 0 : _nameData.Length) +
                                _embeddedBlip.FullByteLength);
#endif
            }
        }

        protected override void WriteNoHeader(OfficeArtWriteContext context)
        {
            Contract.Assert(rhrecVer == 0x02);
            type = (MSOBLIPTYPE) rhrecInstance;
            Contract.Assert(rhrecType == RecType.OfficeArtFBSE);
            Contract.Assert(rhrecType == (RecType) 0xF007);
            context.Write((byte) _btWin32);
            context.Write((byte) _btMacOs);
            Contract.Assert(type == _btWin32 || type == _btMacOs);
            Contract.Assert(_rgbUid != null);
            _rgbUid.Write(context.Writer);
            context.Write(_tag);
            _size = (uint) 0;
            if (_embeddedBlip != null)
                _size = (uint) _embeddedBlip.FullByteLength;
            context.Write(_size);
            context.Write(_cRef);
            context.Write(_foDelay);
            context.Write(_unused1);
            var cbName = (byte) ((_nameData == null) ? 0 : _nameData.Length);
            context.Write(cbName);
            context.Write(_unused2);
            context.Write(_unused3);
            if (_nameData != null)
                context.Write(_nameData);
            if (_embeddedBlip != null) 
            _embeddedBlip.Write(context);
        }

        protected override void PrepareHeader(ref OfficeArtRecordHeader rh)
        {
            rh.recInstance = (ushort) type;
        }

        public override Picture ToPicture()
        {
            return _embeddedBlip.ToPicture();
        }
    }
}